package common.util;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 数据库工具类 - 基于 HikariCP 实现连接池管理
 * <p>
 * 特点：
 * <ul>
 *     <li>使用静态代码块初始化全局唯一的数据源（单例模式）</li>
 *     <li>支持从 jdbc.properties 加载数据库配置</li>
 *     <li>封装了获取连接与数据源的方法</li>
 * </ul>
 */
public final class DBUtil {

    /** 全局唯一的数据源（线程安全、基于连接池） */
    private static final DataSource DATA_SOURCE;

    /** 日志记录器 */
    private static final Logger logger = LoggerFactory.getLogger(DBUtil.class);

    // 静态代码块：类加载时执行一次，用于初始化连接池
    static {
        try {
            // 读取配置文件 jdbc.properties
            Properties props = new Properties();
            try (InputStream input = DBUtil.class.getClassLoader().getResourceAsStream("jdbc.properties")) {
                if (input == null) {
                    throw new RuntimeException("找不到 jdbc.properties 配置文件");
                }
                props.load(input);
            }

            // 配置 HikariCP 参数
            HikariConfig config = new HikariConfig();
            config.setJdbcUrl(props.getProperty("jdbc.url"));
            config.setUsername(props.getProperty("jdbc.username"));
            config.setPassword(props.getProperty("jdbc.password"));

            // 连接池参数（最大连接数 / 最小空闲连接数）
            config.setMaximumPoolSize(Integer.parseInt(props.getProperty("jdbc.pool.maximumPoolSize", "10")));
            config.setMinimumIdle(Integer.parseInt(props.getProperty("jdbc.pool.minimumIdle", "5")));

            // 初始化数据源
            DATA_SOURCE = new HikariDataSource(config);

            logger.info("HikariCP 连接池初始化成功，最大连接数: {}", config.getMaximumPoolSize());
        } catch (Exception e) {
            logger.error("数据库连接池初始化失败", e);
            throw new ExceptionInInitializerError("数据库连接池初始化失败: " + e.getMessage());
        }
    }

    /**
     * 私有构造方法，防止外部实例化工具类。
     */
    private DBUtil() {}

    /**
     * 从连接池中获取数据库连接。
     *
     * @return 可用的 {@link Connection}
     * @throws SQLException 获取连接失败时抛出异常
     */
    public static Connection getConnection() throws SQLException {
        return DATA_SOURCE.getConnection();
    }

    /**
     * 获取全局唯一的数据源。
     *
     * @return 全局唯一的 {@link DataSource}
     */
    public static DataSource getDataSource() {
        return DATA_SOURCE;
    }
}
